package cn.lcfms.cms;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.ListIterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import cn.lcfms.bin.core.Application;
import cn.lcfms.utils.FlagWebsocket;
import cn.lcfms.utils.HttpUtils;

public class Plagiarism {
	private String host;
	private String path;
	private String charset;
	private String cookie;
	private String error;
	private String template;
	private String statics;
	private HashSet<String> imgcode=new HashSet<>();
	private int act=0;
	private StringBuffer content=new StringBuffer();
	private HashSet<String> css=new HashSet<>();
	private HashSet<String> js=new HashSet<>();	
	private HashSet<String> img=new HashSet<>();	
	private HashSet<String> fonts=new HashSet<>();	
	private int num=0;
	private String type;
	
	public String getJs() {
		if(type.equals("jsp")) {
			return "${JS}";
		}
		return "js/";
	}
	public String getCss() {
		if(type.equals("jsp")) {
			return "${CSS}";
		}
		return "css/";
	}
	public String getImg() {
		if(type.equals("jsp")) {
			return "${IMG}";
		}
		return "images/";
	}
	public void setImgcode(String img) {	
		String[] split = img.split(",");
		for(String str:split) {
			imgcode.add(str);
		}
	}

	public void setTypeHtml() {
		type="";
	}
	
	public int getAct() {
		return act;
	}

	public String getError() {
		switch (act) {
		case 1:
			parsecss();
			break;
		case 2:
			parsejs();
			break;
		case 3:
			parseimg();
			break;
		case 4:
			writeCSS();
			break;
		case 5:
			writeJS();
			break;
		case 6:
			writeFonts();
			break;
		case 7:
			writeIMG();
			break;
		case 8:
			createTemp(template);
			break;
		}
		act++;
		return error;
	}


	public Plagiarism(String str,String _charset,String _cookie,String _template,String _statics,String filetype){
		if(_template.indexOf(":")==-1) {
			_template=Application.TEMP_PATH+_template;
		}	
		if(_statics.indexOf(":")==-1) {
			_statics=Application.ROOT_PATH+"statics"+Application.F+_statics;
		}
		if(!_statics.endsWith(Application.F)) {
			_statics=_statics+Application.F;
		}
		this.template=_template;
		this.statics=_statics;
		this.charset=_charset;
		this.cookie=_cookie;
		this.type=filetype;
		imgcode.add("img[src]");
		URL url;
		try {
			url = new URL(str);	
			path=url.getProtocol()+"://"+url.getHost()+url.getFile();
			path=path.substring(0, path.lastIndexOf("/"))+"/";
			host=url.getProtocol()+"://"+url.getHost()+"/";
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36");
			conn.setConnectTimeout(5000);
			conn.setRequestProperty("Cookie", cookie.trim());
			conn.setRequestMethod("GET");
			if (conn.getResponseCode() == 200) {
				System.out.println("获取到模板文件");
				FlagWebsocket.echo(true,"获取到模板文件",1);
				InputStream inputStream = conn.getInputStream();
				String line;
				BufferedReader br = new BufferedReader(new InputStreamReader(inputStream,charset));
				while ((line = br.readLine()) != null) {
					line=backgroundUrl(line,path,true);
				    content.append(line+"\n");
				}
				inputStream.close();
			}else {
				error="请求状态异常："+conn.getResponseCode();
			}
		} catch (MalformedURLException e) {
			error="url格式有错";
		} catch (IOException e) {
			error="IO异常";
		}		
	}
	
	private void parsecss() {
		Document doc = Jsoup.parse(content.toString());
		Elements links = doc.select("link[rel=stylesheet]"); 
		ListIterator<Element> iterator = links.listIterator();
		while (iterator.hasNext()) {
			Element next = iterator.next();
			String attr = next.attr("href");
			if(attr.startsWith("./")) {			
				attr=path+attr.substring(2);
			}
			if(attr.startsWith("//")) {
				attr="http:"+attr;
			}
			if(attr.startsWith("/")) {
				attr=host+attr.substring(1);
			}
			if(!attr.startsWith("http")) {
				attr=path+attr;
			}	
			css.add(attr);
			String file=getFileNameLong(attr);
			next.attr("href",getCss()+file);
		}	
		FlagWebsocket.echo(true,"CSS文件解析完成",1);
		content=new StringBuffer(doc.toString());
	}
	
	private void parsejs() {
		Document doc = Jsoup.parse(content.toString());
		Elements links = doc.select("script[src]"); 
		ListIterator<Element> iterator = links.listIterator();
		while (iterator.hasNext()) {
			Element next = iterator.next();
			String attr = next.attr("src");
			if(attr.startsWith("./")) {			
				attr=path+attr.substring(2);
			}
			if(attr.startsWith("//")) {
				attr="http:"+attr;
			}
			if(attr.startsWith("/")) {
				attr=host+attr.substring(1);
			}
			if(!attr.startsWith("http")) {
				attr=path+attr;
			}
			js.add(attr);
			String shortname = getFileNameShort(attr);
			if(!shortname.endsWith("js")) {
				shortname=shortname+".js";
			}
			next.attr("src",getJs()+shortname);	
		}	
		FlagWebsocket.echo(true,"JS文件解析完成",1);
		content=new StringBuffer(doc.toString());
	}
	
	private void parseimg() {
		Document doc = Jsoup.parse(content.toString());
		for(String imgs:imgcode) {
			Elements links = doc.select(imgs); 
			String n=imgs.substring(imgs.indexOf("[")+1, imgs.indexOf("]"));
			ListIterator<Element> iterator = links.listIterator();
			while (iterator.hasNext()) {
				Element next = iterator.next();
				String attr = next.attr(n);
				attr=attr.trim();
				if(attr.startsWith("./")) {			
					attr=path+attr.substring(2);
				}
				if(attr.startsWith("//")) {
					attr="http:"+attr;
				}
				if(attr.startsWith("/")) {
					attr=host+attr.substring(1);
				}
				if(!attr.startsWith("http")) {
					attr=path+attr;
				}			
				img.add(attr);
				String file=getFileNameLong(attr);
				next.attr(n,getImg()+file);	
			}	
		}
		FlagWebsocket.echo(true,"图片文件解析完成",1);
		content=new StringBuffer(doc.toString());
	}
	
	private void writeCSS() {
		for(String str:css) {
			String path=str.substring(0,str.lastIndexOf("/"))+"/";
			try {
				String filename=getFileNameShort(str);				
				File file=new File(statics+"css"+Application.F+filename);	
				if(file.exists()) {
					continue;
				}
				byte[] b = HttpUtils.browser(str,cookie);
				System.out.println("获取："+str);
				msg(true,"成功获取："+str);
				String cssstr=new String(b, charset);
				if(null==cssstr || cssstr.equals("")) {
					continue;
				}
				String wr=backgroundUrl(cssstr,path,false);							
				FileUtils.writeStringToFile(file, wr, charset);
			} catch (IOException e) {
				msg(false,"获取失败："+str);
				e.printStackTrace();
			} finally {
				num++;
			}
		}		
	}
	
	private void writeFonts() {
		for(String str:fonts) {
			try {
				String filename=getFileNameShort(str);				
				File file=new File(statics+"fonts"+Application.F+filename);	
				if(file.exists()) {
					continue;
				}
				byte[] b = HttpUtils.browser(str,cookie);
				System.out.println("获取："+str);
				msg(true,"成功获取："+str);
				if(b.length==0) {
					continue;
				}						
				FileUtils.writeByteArrayToFile(file, b);
			} catch (IOException e) {
				msg(false,"获取失败："+str);
				e.printStackTrace();
			} finally {
				num++;			
			}
		}	
	}
	
	private String backgroundUrl(String content,String path,boolean tempfile) {
		String preg="url\\(.*?\\)";
		Pattern r1 = Pattern.compile(preg);	
		Matcher m1 = r1.matcher(content);
		while(m1.find()) {
			String group = m1.group();	
			String str=group.substring(group.indexOf("(")+1, group.indexOf(")"));
			if(str.startsWith("'") && str.endsWith("'")) {
				str=str.substring(1,str.length()-1);
			}
			if(str.startsWith("\"") && str.endsWith("\"")) {
				str=str.substring(1,str.length()-1);
			}
			String ds=str.indexOf("?")!=-1?str.substring(0, str.indexOf("?")):str;
			if(ds.endsWith(".png") || ds.endsWith(".jpg") || ds.endsWith(".jpeg") || ds.endsWith(".gif")|| ds.endsWith(".bmp")) {
				if(str.startsWith("./")) {
					str=str.substring(2);
					str=path+str;
				}
				if(str.startsWith("//")) {
					str="http:"+str;
				}
				if(str.startsWith("/")) {
					str=host+str.substring(1);
				}
				if(!str.startsWith("http")) {
					str=path+str;
				}
				img.add(str);
				if(tempfile) {
					content=content.replace(group, "url("+getImg()+getFileNameLong(str)+")");
				}else {
					content=content.replace(group, "url(../images/"+getFileNameLong(str)+")");
				}				
			}
			if(ds.endsWith(".eot") || ds.endsWith(".woff2") ||ds.endsWith(".woff") ||ds.endsWith(".ttf") ||ds.endsWith(".svg")) {
				if(str.startsWith("./")) {
					str=str.substring(2);
					str=path+str;
				}
				if(str.startsWith("//")) {
					str="http:"+str;
				}
				if(str.startsWith("/")) {
					str=host+str.substring(1);
				}
				if(!str.startsWith("http")) {
					str=path+str;
				}
				fonts.add(str);
				content=content.replace(group, "url('../fonts/"+getFileNameLong(str)+"')");
			}			
		}
		return content;
	}
	
	private void writeJS() {
		for(String str:js) {
			try {
				String filename=getFileNameShort(str);
				if(!filename.endsWith("js")) {
					filename=filename+".js";
				}
				File file=new File(statics+"js"+Application.F+filename);
				if(file.exists()) {
					continue;
				}
				byte[] b = HttpUtils.getDataByte(str);
				System.out.println("获取："+str);
				msg(true,"成功获取："+str);
				String cssstr=new String(b, charset);
				if(null==cssstr || cssstr.equals("")) {
					continue;
				}
				FileUtils.writeStringToFile(file, cssstr, charset);
			} catch (IOException e) {
				msg(false,"获取失败："+str);
				e.printStackTrace();
			} finally {
				num++;
			}
		}		
	}
	
	private void writeIMG() {	
		for(String str:img) {
			try {
				if(!str.startsWith("http")) {
					continue;
				}
				String filename=getFileNameShort(str);
				File file=new File(statics+"images"+Application.F+filename);
				if(file.exists()) {
					continue;
				}
				byte[] cssstr = HttpUtils.browser(str,cookie);
				System.out.println("获取："+str);
				msg(true,"成功获取："+str);
				if(cssstr.length==0) {
					continue;
				}			
				FileUtils.writeByteArrayToFile(file, cssstr);	
			}catch (IOException e) {
				msg(false,"获取失败："+str);
				e.printStackTrace();
			} finally {
				num++;
			}
		}		
	}
	
	private String getFileNameLong(String file){
		int index=file.indexOf("?");
		if(index==-1) {
			file=file.substring(file.lastIndexOf("/")+1);
		}else {
			String str = file.substring(0, index);
			file=file.substring(str.lastIndexOf("/")+1);
		}
		return file;	
	}
	
	private String getFileNameShort(String file){
		int index=file.indexOf("?");
		index=index>0?index:file.indexOf("#");
		if(index==-1) {
			file=file.substring(file.lastIndexOf("/")+1);
		}else {
			file = file.substring(0, index);
			file=file.substring(file.lastIndexOf("/")+1);
		}
		return file;
	}
	
	private void createTemp(String template){			
		File file=new File(template);
		try {
			String top="";
			if(type.equals("jsp")) {
				top="<%@ page language=\"java\" contentType=\"text/html\"  pageEncoding=\""+charset+"\"%>\n<%@ taglib prefix=\"c\" uri=\"http://java.sun.com/jsp/jstl/core\"%>\n";				
			}
			FileUtils.writeStringToFile(file, top+content.toString(), "utf-8");
		} catch (IOException e) {
			error="创建模板文件失败";
		}  
	}
	
	private void msg(boolean success,String msg) {
		float i=num*100/(img.size()+css.size()+fonts.size()+js.size());
		FlagWebsocket.echo(success,msg,Math.floor(i));
	}
}
